/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.aplink.generic.google.datetimepicker;

import java.util.Calendar;

import android.animation.Keyframe;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.annotation.SuppressLint;
import android.os.Build;
import android.text.format.Time;
import android.view.View;

/**
 * Utility helper functions for time and date pickers.
 */
public class Utils {

	// Alpha level for fully opaque.
	public static final int FULL_ALPHA = 255;
	public static final int MONDAY_BEFORE_JULIAN_EPOCH = Time.EPOCH_JULIAN_DAY - 3;

	public static final int PULSE_ANIMATOR_DURATION = 544;
	// Alpha level for time picker selection.
	public static final int SELECTED_ALPHA = 51;
	public static final int SELECTED_ALPHA_THEME_DARK = 102;

	static final String SHARED_PREFS_NAME = "com.android.calendar_preferences";

	public static int getDaysInMonth(final int month, final int year) {
		switch (month) {
			case Calendar.JANUARY:
			case Calendar.MARCH:
			case Calendar.MAY:
			case Calendar.JULY:
			case Calendar.AUGUST:
			case Calendar.OCTOBER:
			case Calendar.DECEMBER:
				return 31;
			case Calendar.APRIL:
			case Calendar.JUNE:
			case Calendar.SEPTEMBER:
			case Calendar.NOVEMBER:
				return 30;
			case Calendar.FEBRUARY:
				return ((year % 4) == 0) ? 29 : 28;
			default:
				throw new IllegalArgumentException("Invalid Month");
		}
	}

	/**
	 * Takes a number of weeks since the epoch and calculates the Julian day of
	 * the Monday for that week.
	 *
	 * This assumes that the week containing the {@link Time#EPOCH_JULIAN_DAY}
	 * is considered week 0. It returns the Julian day for the Monday
	 * {@code week} weeks after the Monday of the week containing the epoch.
	 *
	 * @param week
	 *            Number of weeks since the epoch
	 * @return The julian day for the Monday of the given week since the epoch
	 */
	public static int getJulianMondayFromWeeksSinceEpoch(final int week) {
		return Utils.MONDAY_BEFORE_JULIAN_EPOCH + (week * 7);
	}

	/**
	 * Render an animator to pulsate a view in place.
	 *
	 * @param labelToAnimate
	 *            the view to pulsate.
	 * @return The animator object. Use .start() to begin.
	 */
	public static ObjectAnimator getPulseAnimator(final View labelToAnimate,
			final float decreaseRatio, final float increaseRatio) {
		final Keyframe k0 = Keyframe.ofFloat(0f, 1f);
		final Keyframe k1 = Keyframe.ofFloat(0.275f, decreaseRatio);
		final Keyframe k2 = Keyframe.ofFloat(0.69f, increaseRatio);
		final Keyframe k3 = Keyframe.ofFloat(1f, 1f);

		final PropertyValuesHolder scaleX = PropertyValuesHolder.ofKeyframe(
				"scaleX", k0, k1, k2, k3);
		final PropertyValuesHolder scaleY = PropertyValuesHolder.ofKeyframe(
				"scaleY", k0, k1, k2, k3);
		final ObjectAnimator pulseAnimator = ObjectAnimator
				.ofPropertyValuesHolder(labelToAnimate, scaleX, scaleY);
		pulseAnimator.setDuration(Utils.PULSE_ANIMATOR_DURATION);

		return pulseAnimator;
	}

	/**
	 * Returns the week since {@link Time#EPOCH_JULIAN_DAY} (Jan 1, 1970)
	 * adjusted for first day of week.
	 *
	 * This takes a julian day and the week start day and calculates which week
	 * since {@link Time#EPOCH_JULIAN_DAY} that day occurs in, starting at 0.
	 * *Do not* use this to compute the ISO week number for the year.
	 *
	 * @param julianDay
	 *            The julian day to calculate the week number for
	 * @param firstDayOfWeek
	 *            Which week day is the first day of the week, see
	 *            {@link Time#SUNDAY}
	 * @return Weeks since the epoch
	 */
	public static int getWeeksSinceEpochFromJulianDay(final int julianDay,
			final int firstDayOfWeek) {
		int diff = Time.THURSDAY - firstDayOfWeek;
		if (diff < 0) {
			diff += 7;
		}
		final int refDay = Time.EPOCH_JULIAN_DAY - diff;
		return (julianDay - refDay) / 7;
	}

	public static boolean isJellybeanOrLater() {
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
	}

	/**
	 * Try to speak the specified text, for accessibility. Only available on JB
	 * or later.
	 *
	 * @param text
	 *            Text to announce.
	 */
	@SuppressLint("NewApi")
	public static void tryAccessibilityAnnounce(final View view,
			final CharSequence text) {
		if (Utils.isJellybeanOrLater() && (view != null) && (text != null)) {
			view.announceForAccessibility(text);
		}
	}
}
